﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace Clustering_IA_Project
{
    public partial class FinestraClustering : Form
    {
        List<WordXML> listWord;
        DocTermMatrix dc;
        SimilarityMatrix sm;
        List<string> file;
        delegate void SetTextCallback(string text);
        bool flag = true;
        string nameFileRequest = "";

        /// <summary>
        /// Costruttore
        /// </summary>
        public FinestraClustering()
        {
            InitializeComponent();

            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"D:\xml";
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
            watcher.Filter = "*.xml";
            watcher.Created += new FileSystemEventHandler(createFile);
            watcher.EnableRaisingEvents = true;
            string startMessage = "I.A. Clustering module started\n ";
            richTextBox1.AppendText(startMessage);
        }

        /// <summary>
        /// Monitora se vengono scritti file nella cartella xmlricevuti
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void createFile(object source, FileSystemEventArgs e)
        {
            setText("ricevimento dati...");
            while (true)
            {
                if (FileUploadCompleted(e.FullPath))
                {
                    setText("dati ricevuti correttamente\n");
                    this.start();
                    break;
                }
            }
        }

        /// <summary>
        /// Controlla che il file sia uppato tutto
        /// </summary>
        /// <param name="filename">nome del file</param>
        /// <returns>ritorna true se l'uppload e' stato completato, viceversa false</returns>
        private static bool FileUploadCompleted(string filename)
        {
            try
            {
                using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None)) { 
                    return true; 
                }
            }
            catch (IOException) 
            { 
                return false; 
            }
        }

        /// <summary>
        /// scrive nel box text
        /// </summary>
        private void setText(string text)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(setText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.richTextBox1.AppendText(text);
            }
        }

        /// <summary>
        /// Legge i nomi di tutti i file presenti in una directory
        /// </summary>
        private List<string> readFile()
        {
            List<string> file = new List<string>();
            foreach (string directoryPath in Directory.GetFiles(@"D:\xml"))
            {
                if (directoryPath.Equals("request.xml"))
                {
                    flag = false;
                    file.Clear();  
                    file.Add(directoryPath);
                    nameFileRequest = directoryPath;
                    return file;
                }
                else
                {
                    //leggo solo i nuovi file che arrivano
                    if(!file.Contains(directoryPath))
                        file.Add(directoryPath);
                }
            }
            flag = true;
            return file;
        }

        public void start()
        {
            file = readFile();
            //devo elaborare informazioni
            if (flag)
            {
                XmlReader xr = new XmlReader();
                listWord = xr.read(file);
                stampalw();
                
                dc = new DocTermMatrix(listWord);
                dc.createMatrix();
                stampaDC();

                sm = new SimilarityMatrix(listWord, dc);
                sm.createMatrix();
                stampaSExtended();
                stampaS();
            }
            //devo elaborare richieste
            else
            {
                ReadRequest rr = new ReadRequest();
                Request rq = rr.ReadXML(file[0].Trim());
                File.Delete(nameFileRequest);  //assume la richiesta e la consuma
                if (listWord.Count == 0)
                {
                    setText(@"è stata ricevuta una richiesta di recommender dall'utente: " + rq.user + "\n");
                    setText(@"...purtroppo non vi sono abbastanza dati per poter erogare il servizio" + " \n");
                    //TODO invia trasmossione vuota
                }
                else
                {
                    setText(@"è stata ricevuta una richiesta di recommender dall'utente: " + rq.user + "\n");




                }
            }
        }

        /// <summary>
        /// Metodo per i test stampa nella console il contenuto dell'xml
        /// </summary>
        public void stampalw()
        {
            setText("Dati ricevuti\n");
            foreach (WordXML x in listWord)
            {                
                setText("word:" +  x.word + "\n");
                setText("web page:" + x.webPage + ":" + x.numPageWord + "\n");
                setText("numero fissazioni:" + x.fixNumb.ToString() + "\n");
                setText("tempo di fissazione:" + x.fixTime.ToString() + "\n");
                setText("idf:" + x.idf.ToString() + "\n");
                setText("contesto:");
                foreach (String s in x.context)
                {
                    setText("\t" + s + "\t");
                }
                setText("\ntempi di fissazione del contesto:");
                foreach (float f in x.contextFixTime)
                {
                    setText("\t" + f.ToString() + "\t");
                }
                setText("\ntempo medio di fissazione per ogni parola del contesto" + x.tfcMeans.ToString() + "\n");
            }
            setText("Fine dati ricevuti\n\n");
        }

        /// <summary>
        /// Metodo per i test stampa nella console la matrice dc
        /// </summary>
        public void stampaDC()
        {
            setText("Matrice DocTerms\n");
            foreach ( rigaDocTerm r in dc.getMatrix())
            {
                foreach (KeyValuePair<WordXML, float> pair in r.riga)
                {
                    setText("[" + pair.Value + "]  ");
                }
                setText("\n");
            }
            setText("Fine matrice DocTerms\n\n");
        }

        /// <summary>
        /// Metodo per i test stampa nella console la matrice di similarita'
        /// </summary>
        public void stampaS()
        {
            setText("Matrice Similarity\n");
            string w = sm.getMatrix()[0].x;
            foreach (Item i in sm.getMatrix())
            {
                if ((i.x.Equals(w)))
                    setText("[" + i.similarity + "]   ");
                else
                {
                    w = i.x;
                    setText("\n[" + i.similarity + "]   ");
                }
            }
            setText("\nFine matrice Similarity\n\n");
        }

        /// <summary>
        /// Metodo per i test stampa nella console la matrice di similarita' testualmente
        /// </summary>
        public void stampaSExtended()
        {
            setText("Matrice Similarity\n");
            foreach (Item i in sm.getMatrix())
            {
                setText("page1: " + i.x + "\n" + "page2: " + i.y + "\n" + @"similarità: " + i.similarity + "\n");
            }
            setText("Fine matrice Similarity\n\n");
        }
    }
}
